from sets import Set
import re

class IdGenerator:

    """
    generates a member id from a string. Used for suggesting a member id when 
    adding contact as member
    """

    def __init__(self, aStr, usedIds):
        self.aStr = self._cleaner(aStr).split() # a list of words
        self.usedIds = Set(usedIds) # set of used ids. New id must be different
        self._id_attempts = 0
        self._id_prepend = 1

    def _cleaner(self, aStr):
        # replace latin-1 chars with 'x'
        aStr = aStr.encode('ascii', 'replace').replace('?', 'x')
        # cleans the string for illegal chars in zope ids
        illegalChars = re.compile('[^a-zA-Z_ 0-9]*')
        return re.sub(illegalChars, '', aStr.lower())

    def maxLen(self):
        # the maximum possible length of the id from the provided string
        # return reduce(lambda x, y: x+y, map(len, self.aStr))
        return len(''.join(self.aStr))

    def generate(self):
        # set up initial values
        usedIds = self.usedIds
        names = self.aStr
        # try first name
        memberId = names[0]
        if not memberId in usedIds:
            return memberId
        # try last name
        memberId = names[-1]
        if not memberId in usedIds:
            return memberId
        # then try n letters from beginning of each word
        longest_name = max([len(name) for name in names])
        for i in range(1, longest_name+1):
            memberId = ''.join([name[:i] for name in names])
            if not memberId in usedIds:
                return memberId
        # try first name with increasingly large number appended
        # this should never fail
        n = 1
        first_name = names[0]
        while 1:
            memberId = '%s%s' % (first_name, n)
            n += 1
            if not memberId in usedIds:
                return memberId
